package com.qire.manhua.view.comicReader.renderer;

import android.graphics.Rect;
import android.os.SystemClock;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

/**
 * 弹幕池
 * Created by Administrator on 2018/4/20.
 */
public class BulletScreenPool {

    /**
     * key url ,value BulletScreen*/
    private final HashMap<String, ArrayList<BulletScreen>> mBulletScreenPool = new HashMap<>();

    private boolean allowLoopPlay = true;

    private int poolIndex = 0;
    private int poolCount = 100;
    private BulletScreen[] visibleBulletScreensPool = new BulletScreen[poolCount];

    public BulletScreenPool(){
    }

    public void loadBulletScreen(String key, BulletScreen bulletScreen){
        ArrayList<BulletScreen> list = mBulletScreenPool.get(key);
        if(list == null){
            list = new ArrayList<>();
            mBulletScreenPool.put(key,list);
        }
        if(!list.contains(bulletScreen))
            list.add(bulletScreen);
    }

    private long addTime = 0;
    /***
     * 从弹幕池里获取需要被显示的可见弹幕，该方法会筛选出重复位置的弹幕。
     * @param screenArea 显示区域
     * @return 返回一个弹幕数组，如果弹幕没有，那么返回一个空数组。该返回不为null*/
    public BulletScreen[] fetchVisibleBulletScreen(Rect screenArea, PictureResource[] visiblePictureResources) {

    	PictureResource[] pages = visiblePictureResources;
        timeoutChecks();
//        screenOutChecks(screenArea);
        boolean needModify =  poolIndex < poolCount;
        boolean canAdded = false;
        
        canAdded = SystemClock.uptimeMillis()-addTime>200;
        
        if(needModify && canAdded) {
        	addTime = SystemClock.uptimeMillis();

            ArrayList<BulletScreen> list = new ArrayList<>();

            //todo: 业务逻辑有修改，需要在池子之上在提取一层管道层用以循环显示
        	for(PictureResource page : pages) {
        		if(page==null) continue;
                ArrayList<BulletScreen> tmpList = mBulletScreenPool.get(page.token);
                if(tmpList!=null&&!tmpList.isEmpty())
                    list.addAll(tmpList);
            }

            if(list != null && !list.isEmpty()) {
//                Collections.shuffle(list);
                for (BulletScreen bulletScreen : list) {

                    if(poolIndex >= poolCount || !canAdded)
                        break;
                    if(bulletScreen == null)
                        continue;
                    if(!bulletScreen.existIn(screenArea))
                        continue;
                    if(!isHaveShow(bulletScreen))
                        continue;

                    canAdded = !putVisiblePool(bulletScreen);

                }
                limitShowCount = Math.max(minShowCount+1,limitShowCount);
                minShowCount   = Integer.MAX_VALUE;
            }
        }
        return poolIndex <=0 ? new BulletScreen[0] : visibleBulletScreensPool;
    }

    private int minShowCount= Integer.MAX_VALUE, limitShowCount = 0;
    private boolean isHaveShow(BulletScreen bulletScreen){
        if(allowLoopPlay){
            int showCount = bulletScreen.getShowCount();
            boolean isHaveShow = showCount < limitShowCount;
            minShowCount = Math.min(showCount,minShowCount);
            return isHaveShow;
        } else {
            return !bulletScreen.isHaveShow();
        }
    }

    private boolean putVisiblePool(BulletScreen bulletScreen){
    	boolean addSucceed = false;
        for(BulletScreen visibleBulletScreen : visibleBulletScreensPool){
            if(visibleBulletScreen != null && visibleBulletScreen.equals(bulletScreen)){
                return addSucceed;
            }
        }
        if(poolIndex < poolCount) {
            for(int index=poolIndex;index>=0;index--) {
                if(bulletScreen.needCorrectionLocation(visibleBulletScreensPool[index])){
//                	long time = SystemClock.uptimeMillis() - visibleBulletScreensPool[index].getShowStartTime();
//                	if(time<300)//500)
                		return addSucceed;
//                    break;
                }
            }
            visibleBulletScreensPool[poolIndex++] = bulletScreen.getShow();
            addSucceed = true;
        }
        return addSucceed;
    }

    private BulletScreen removeVisiblePool(BulletScreen bulletScreen){ 
        boolean isMove = false;

        for(int index=0;index < visibleBulletScreensPool.length; index++) {
        	BulletScreen tmpBulletScreen = visibleBulletScreensPool[index];
        	
        	BulletScreen moveBulletScreen = index >= visibleBulletScreensPool.length-1 ?  
        									null : visibleBulletScreensPool[index+1];
        	
        	if(tmpBulletScreen == bulletScreen){
        		visibleBulletScreensPool[index] = moveBulletScreen;
        		isMove = true;
        		if(poolIndex>0)
        			poolIndex--;
        	}else if(isMove){
        		visibleBulletScreensPool[index] = moveBulletScreen;
        	}
        }
        
        return bulletScreen;
    }

    /***
     * @return 如果显示弹幕缓存中存在超时的弹幕则移除弹幕，并返回teur否则返回fasle*/
    private boolean timeoutChecks(){
        boolean haveRevised = false;
        for(BulletScreen bulletScreen : visibleBulletScreensPool){
            if(bulletScreen!=null && bulletScreen.isTimeout()) {
                removeVisiblePool(bulletScreen);
                haveRevised = true;
            }
        }
        return haveRevised;
    }

    /**
     * @return 如果显示弹幕缓存中存在超出屏幕的弹幕则移除弹幕，并返回teur否则返回fasle*/
    private boolean screenOutChecks(Rect screenArea) {
        boolean haveRevised = false;
        for(BulletScreen bulletScreen : visibleBulletScreensPool) {
            if(bulletScreen!=null && !bulletScreen.existIn(screenArea)) {
                removeVisiblePool(bulletScreen);
                bulletScreen.reset();
                haveRevised = true;
            }
        }
        return haveRevised;
    }

    public void release() {
    	mBulletScreenPool.clear();
    	Arrays.fill(visibleBulletScreensPool, null);
    }
}
